#include "ext.h"
/*
you'll need to make sure your search paths can find jni.h
*/
#include "libmaxygen.h"

#define libname "libmaxygen"
#define debug 0

/*
 * Class:     maxygen_libmaxygen
 * Method:    getpsave0
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_maxygen_libmaxygen_getpsave0(JNIEnv *env, jobject jthis, jstring jobname, jstring jthisname)
{
	// Max 4.6 version
	
	/* convert from java to c */
	char *cobname = (*env)->GetStringUTFChars(env, jobname, 0);
	char *cthisname = (*env)->GetStringUTFChars(env, jthisname, 0);

#if debug
	post("calling Java_libmaxygen_getpsave0");
#endif

	char *cbinbuf = maxygen_getpsave(cobname, cthisname);
	
	/* clean up */
	(*env)->ReleaseStringUTFChars(env, jobname, cobname);
	(*env)->ReleaseStringUTFChars(env, jthisname, cthisname);

#if debug
	post("returning Java_libmaxygen_getpsave0");
#endif
	
	/* return */
	return((*env)->NewStringUTF(env, cbinbuf));
}

/*
 * Class:     maxygen_libmaxygen
 * Method:    getpsave50
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_maxygen_libmaxygen_getpsave50(JNIEnv *env, jobject jthis, jstring jobname, jstring jthisname)
{
	// Max 5 version
	return((*env)->NewStringUTF(env, "dummy")); 
}

short maxygen_patcher_eachfun(t_patcher *p, m_psave *data)
{
	t_box *b;
	t_symbol *obsym = gensym(data->obname);
	t_symbol *thissym = gensym(data->thisname);
	t_symbol *bbsym = 0L;
	short ret = 1;
	
#if debug
	post("calling maxygen_patcher_eachfun");
#endif
	
	/* find our mxj object */
	b = maxygen_getnamedbox(p, thissym);
	
	if(!b) {
		ret = 0;
		goto out; /* not in this patch keep searching patchers */
	}	
	
	/* then find the object in the same patcher we're looking  for */
	b = maxygen_getnamedbox(p, obsym); 
	
	if(!b) {
		// try subpatchers named: more, more[1] etc 
		
		b = p->p_box;
		
		while(b) {
			t_patcher *sub = b->b_firstin;
			
			if(sub) {
				if(ob_sym(sub)==gensym("patcher") && maxygen_isnamemore(p,b)) {
					t_box *sb = maxygen_getnamedbox(sub, obsym); 
					
					if(sb) {
						b = sb;
						break;
					}
				}
			}
			b = b->b_next;
		}
			
	}
	
	if(b) {
		bbsym = maxygen_getpsavesym(b);
		
		if(bbsym) {
			data->binbuf = bbsym->s_name;
		}
	}
	
out:
#if debug
	post("return maxygen_patcher_eachfun");
#endif
	return ret;
}

char *maxygen_getpsave(char *obname, char *thisname)
{
	// this looks unsafe... I'm returning a temporary variable, if this returned a 
	// t_symbol* it would be OK
	
	m_psave data;
	
#if debug
	post("calling maxygen_getpsave");
#endif
	
	data.obname = obname;
	data.thisname = thisname;
	data.binbuf = 0L; /* the successful patcher_eachdo iteration should fill this field*/
	
	patcher_eachdo((eachdomethod)maxygen_patcher_eachfun, &data);
	
#if debug
	post("returning maxygen_getpsave");
#endif	
	
	return data.binbuf;
}

t_box *maxygen_getnamedbox(t_patcher *p, t_symbol *s)
{
	t_box *b = p->p_box; // the boxes
	
	while(b) {
		if(maxygen_getboxname(p,b)==s)
			return b;
		else
			b = b->b_next;
	}
	
	return 0L;
}

t_symbol *maxygen_getboxname(t_patcher *p, t_box *b)
{
	t_symbol *s;
	
	patcher_boxname(p, b, &s);
	
	return s; // NULL if empty
} 

int maxygen_isnamemore(t_patcher *p, t_box *b)
{
	t_symbol *s = maxygen_getboxname(p,b);
	
	if(!s)
		return 0;
	else {
		char *n = s->s_name;
		
		if(n[0]=='m' && n[1]=='o' && n[2]=='r' && n[3]=='e' && (n[4]=='[' || n[4]==0))
			return 1;
		else
			return 0;
	}
} 

t_symbol *maxygen_getpsavesym(t_box *b)
{
	void *bb = binbuf_new();
	char **text;
	char *str;
	long size;
	t_symbol *sym;
	
	mess1((t_object *)b,gensym("psave"),bb);
	
	text = newhandle(0);
	binbuf_totext(bb, text, &size);
	
	growhandle(text, size+1);
	
	str = *text;
	str[size] = 0;
	
	sym = gensym(str);
	
	disposhandle(text);
	binbuf_free(bb);
	
	return sym;
}